package top.suven.base.core.rpc;


import org.springframework.boot.WebApplicationType;
import top.suven.base.core.config.DubboSentinelConfig;
import top.suven.base.util.constants.GlobalConstants;
import com.alibaba.csp.sentinel.init.InitExecutor;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
import com.alibaba.csp.sentinel.util.AppNameUtil;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;

import com.alibaba.dubbo.config.annotation.Service;
import org.reflections.Reflections;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;


/**
 * RPC SERVER 启动服务实现类，加载提升到30秒启动完成
 * @param
 */
@EnableTransactionManagement
@SpringBootApplication(exclude = {
        DataSourceAutoConfiguration.class,DruidDataSourceAutoConfigure.class,
        HibernateJpaAutoConfiguration.class
       })
@Configuration
@ComponentScan(basePackages={GlobalConstants.COMPONENT_SCAN_BASE_PACKAGES})
public  abstract  class AbstractRpcServerApplication implements CommandLineRunner,ApplicationContextAware {

    private static  final Logger logger = LoggerFactory.getLogger(AbstractRpcServerApplication.class);

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void run(String... args) throws Exception {
        logger.warn("Started RPC SERVER INTO RUN Successfully ...");
    }

    public static void buildRpc(Class<?> clazz, String ... args){
        new SpringApplicationBuilder(clazz).web(WebApplicationType.NONE)
                .run(args);
    }
//    /**
//     * @Title: DUBBO-SENTINEL启动
//     * @Description: dubbo流量哨兵启动
//     * @param
//     * @return
//     * @throw
//     * @author lixiangling
//     * @date 2018/9/4 15:07
//     *  --------------------------------------------------------
//     *  modifyer    modifyTime                 comment
//     *
//     *  --------------------------------------------------------
//     */
//    @PostConstruct
//    public void init(){
//        DubboSentinelConfig dubboSentinelConfig = applicationContext.getBean(DubboSentinelConfig.class);
//        Reflections reflections = new Reflections(GlobalConstants.DEPICT_PACKAGE, new TypeAnnotationsScanner());
//        Set<Class<?>> classes =  reflections.getTypesAnnotatedWith(Service.class);
//        if(classes == null || classes.isEmpty()){
//            return;
//        }
//        List<FlowRule> flowRuleList = new ArrayList<>();
//        List<DegradeRule> degradeRuleList = new ArrayList<>();
//        for(Class<?> refClass : classes){
//            Class[] parentClasses = refClass.getInterfaces();
//            if(parentClasses == null || parentClasses.length == 0){
//                continue;
//            }
//            String className = parentClasses[0].getName();
//            Method[] methods = parentClasses[0].getDeclaredMethods();
//            if(methods == null || methods.length == 0){
//                continue;
//            }
//            setDubboSentinel(methods,className,dubboSentinelConfig,flowRuleList,degradeRuleList);
//        }
//        if(dubboSentinelConfig.isOpenFlow()||dubboSentinelConfig.isDeGrade()){
//            System.setProperty("user.home", dubboSentinelConfig.getLogPath());
//            System.setProperty(TransportConfig.CONSOLE_SERVER,dubboSentinelConfig.getDashboardServer());
//            System.setProperty(AppNameUtil.APP_NAME,dubboSentinelConfig.getProjectName());
//            if(dubboSentinelConfig.getApiPort()>-1) {
//                System.setProperty(TransportConfig.SERVER_PORT, String.valueOf(dubboSentinelConfig.getApiPort()));
//            }
//            InitExecutor.doInit();
//        }
//
//        if(dubboSentinelConfig.isOpenFlow()&&!flowRuleList.isEmpty()){
//            FlowRuleManager.loadRules(flowRuleList);
//        }
//        if(dubboSentinelConfig.isDeGrade()&&!flowRuleList.isEmpty()){
//            DegradeRuleManager.loadRules(degradeRuleList);
//        }
//
//    }
//
//    private void setDubboSentinel(Method[] methods,String className, DubboSentinelConfig dubboSentinelConfig,List<FlowRule> flowRuleList,List<DegradeRule> degradeRuleList){
//        for (Method method : methods){
//            String methodName = method.toString();
//            methodName = methodName.substring(methodName.indexOf(className)+className.length()+1,methodName.lastIndexOf(")")+1);
//            FlowRule flowRule = new FlowRule();
//            flowRule.setResource(String.format("%s:%s",className,methodName));
//            flowRule.setCount(dubboSentinelConfig.getCount());
//            flowRule.setGrade(dubboSentinelConfig.getGrade());
//            if(dubboSentinelConfig.getStrategy() > -1) {
//                flowRule.setStrategy(RuleConstant.STRATEGY_CHAIN);
//            }
//            if(dubboSentinelConfig.getControlBehavior() > -1) {
//                flowRule.setControlBehavior(dubboSentinelConfig.getControlBehavior());
//            }
//            flowRuleList.add(flowRule);
//
//            DegradeRule degradeRule = new DegradeRule();
//            degradeRule.setGrade(dubboSentinelConfig.getDeGrade());
//            degradeRule.setCount(dubboSentinelConfig.getCount());
//            degradeRule.setResource(flowRule.getResource());
//            degradeRuleList.add(degradeRule);
//        }
//    }
}
